package net.hn.hnms.biz.safety.monitor.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import net.hn.hnms.biz.api.feign.model.DataStateVo;
import net.hn.hnms.biz.api.mine.RemoteMineInfoService;
import net.hn.hnms.biz.api.mine.model.AlarmMessageItemVo;
import net.hn.hnms.biz.api.mine.model.MineVo;
import net.hn.hnms.biz.api.mine.model.SysModelVo;
import net.hn.hnms.biz.api.safety.location.model.OutLimitAlarmingInfoVO;
import net.hn.hnms.biz.api.safety.monitor.model.*;
import net.hn.hnms.biz.api.safety.water.model.SubsidenceAnalysisVo;
import net.hn.hnms.biz.common.jpa.utils.HqlUtils;
import net.hn.hnms.biz.common.jpa.utils.ResponsePage;
import net.hn.hnms.biz.safety.monitor.domain.*;
import net.hn.hnms.biz.safety.monitor.domain.dto.DataConfiginfoDto;
import net.hn.hnms.biz.safety.monitor.domain.dto.PointListVO;
import net.hn.hnms.biz.safety.monitor.domain.vo.ChartAnaliseVo;
import net.hn.hnms.biz.safety.monitor.domain.vo.GasAnalysisVo;
import net.hn.hnms.biz.safety.monitor.domain.vo.keyAreasVo;
import net.hn.hnms.biz.safety.monitor.mapper.BaseSensorInfoNowMapper;
import net.hn.hnms.biz.safety.monitor.mapper.SensorAlarmCountStatMapper;
import net.hn.hnms.biz.safety.monitor.mapper.SensorImportanceConfigMapper;
import net.hn.hnms.biz.safety.monitor.mapper.SensorMonitorNowMapper;
import net.hn.hnms.biz.safety.monitor.repository.AqjkHisSensorMonitorRepository;
import net.hn.hnms.biz.safety.monitor.repository.SensorAlarmEntityRepository;
import net.hn.hnms.biz.safety.monitor.utils.OweDateUtils;
import net.hn.hnms.sys.common.core.constant.Constants;
import net.hn.hnms.sys.common.core.domain.R;
import net.hn.hnms.sys.common.core.exception.HuaNengException;
import net.hn.hnms.sys.common.core.utils.DateUtils;
import net.hn.hnms.sys.common.redis.domain.SysOrganization;
import net.hn.hnms.sys.common.redis.utils.RedisUtils;
import net.hn.hnms.sys.system.api.domain.SysDictData;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 智呈物联 pan'sx
 * 2022/8/3 14:56
 * 1.0 version
 */
@Service
public class SafetyMonitorServiceImpl implements SafetyMonitorService {
    @Autowired
    private JdbcTemplate monitorJdbcTemplate;
    @Autowired
    @Qualifier("monitorEntityManager")
    private EntityManager monitorEntityManager;
    @Autowired
    private RemoteMineInfoService remoteMineInfoService;
    @Autowired
    private AqjkHisSensorMonitorRepository aqjkHisSensorMonitorRepository;
    //    private final AqjkNowBaseSensorinfoRepository aqjkNowBaseSensorinfoRepository;
    @Autowired
    private SensorAlarmEntityRepository sensorAlarmEntityRepository;

    /**
     * 测点实时统计信息Mapper
     */
    @Resource
    private SensorMonitorNowMapper sensorMonitorNowMapper;

    /**
     * 测点实时基本信息
     */
    @Resource
    private BaseSensorInfoNowMapper baseSensorInfoNowMapper;

    /**
     * 测点异常实时数据Mapper
     */
    @Resource
    private SensorAlarmCountStatMapper sensorAlarmCountStatMapper;

    /**
     * 重点区域传感器配置Mapper
     */
    @Resource
    private SensorImportanceConfigMapper sensorImportanceConfigMapper;

    @Override
    public MonitorTodayInfo getTodayInfo(String mineCode) {
        String sql = "select count(1) as count,alramlevel as alram_level,sensor_type from " +
                "( " +
                "SELECT  " +
                "		CASE sensor_type " +
                "			WHEN  '0004'  " +
                "			then " +
                "				case  " +
                "					when  extract(epoch FROM ( end_time- begin_time ))<=900  " +
                "					then  " +
                "						case  " +
                "							when (max_value<50 and max_value>=24) then '蓝色预警' " +
                "							when (max_value<90 and max_value>=50) then '蓝色预警' " +
                "							when (max_value<200 and max_value>=90) then '黄色预警' " +
                "							when ( max_value>=200) then '橙色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))<=1500 and  extract(epoch FROM ( end_time- begin_time ))>900 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<50 and max_value>=24) then '蓝色预警' " +
                "							when (max_value<90 and max_value>=50) then '黄色预警' " +
                "							when (max_value<200 and max_value>=90) then '黄色预警' " +
                "							when ( max_value>=200) then '橙色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))<=1800 and  extract(epoch FROM ( end_time- begin_time ))>1500 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<50 and max_value>=24) then '黄色预警' " +
                "							when (max_value<90 and max_value>=50) then '黄色预警' " +
                "							when (max_value<200 and max_value>=90) then '橙色预警' " +
                "							when ( max_value>=200) then '红色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))>1800 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<50 and max_value>=24) then '黄色预警' " +
                "							when (max_value<90 and max_value>=50) then '橙色预警' " +
                "							when (max_value<200 and max_value>=90) then '红色预警' " +
                "							when ( max_value>=200) then '红色预警'  " +
                "						end " +
                "				end " +
                "			WHEN  '0001'  " +
                "			then " +
                "				case  " +
                "					when  extract(epoch FROM ( end_time- begin_time ))<=900  " +
                "					then  " +
                "						case  " +
                "							when (max_value<1 and max_value>=0.5) then '蓝色预警' " +
                "							when (max_value<1.5 and max_value>=1) then '蓝色预警' " +
                "							when (max_value<2 and max_value>=1.5) then '黄色预警' " +
                "							when ( max_value>=2) then '橙色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))<=1500 and  extract(epoch FROM ( end_time- begin_time ))>900 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<1 and max_value>=0.5) then '蓝色预警' " +
                "							when (max_value<1.5 and max_value>=1) then '黄色预警' " +
                "							when (max_value<2 and max_value>=1.5) then '黄色预警' " +
                "							when ( max_value>=2) then '橙色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))<=1800 and  extract(epoch FROM ( end_time- begin_time ))>1500 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<1 and max_value>=0.5) then '黄色预警' " +
                "							when (max_value<1.5 and max_value>=1) then '黄色预警' " +
                "							when (max_value<2 and max_value>=1.5) then '橙色预警' " +
                "							when ( max_value>=2) then '红色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))>1800 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<1 and max_value>=0.5) then '黄色预警' " +
                "							when (max_value<1.5 and max_value>=1) then '橙色预警' " +
                "							when (max_value<2 and max_value>=1.5) then '红色预警' " +
                "							when ( max_value>=2) then '红色预警'  " +
                "						end " +
                "				end " +
                "		END as alramLevel, " +
                "sensor_type,id " +
                "FROM     dwd_aqjk_now_sensoralarm_count_stat  " +
                "where   (sensor_type = '0004' or  sensor_type='0001') and end_time is not null  and max_value  is not  null  " +
                "and (end_time>CURRENT_DATE  or begin_time>CURRENT_DATE ) and outlier_type='001' %s " +
                ")t GROUP BY alramlevel,sensor_type";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        //sensor_type 0001 环境瓦斯   0004 一氧化碳      outlier_type 001超限报警
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql, mineCode));
        MonitorTodayInfo monitorTodayInfo = new MonitorTodayInfo();
        MonitorTodayInfo.Item itemBlue = monitorTodayInfo.new Item();
        itemBlue.setCh4(0L);
        itemBlue.setCo(0L);
        MonitorTodayInfo.Item itemYellow = monitorTodayInfo.new Item();
        itemYellow.setCh4(0L);
        itemYellow.setCo(0L);
        MonitorTodayInfo.Item itemOrange = monitorTodayInfo.new Item();
        itemOrange.setCh4(0L);
        itemOrange.setCo(0L);
        MonitorTodayInfo.Item itemRed = monitorTodayInfo.new Item();
        itemRed.setCh4(0L);
        itemRed.setCo(0L);
        for (Map<String, Object> map : maps) {
            if ("蓝色预警".equals(map.get("alram_level"))) {
                if ("0004".equals(map.get("sensor_type"))) {
                    itemBlue.setCo((Long) map.get("count"));
                } else {
                    itemBlue.setCh4((Long) map.get("count"));
                }
            } else if ("黄色预警".equals(map.get("alram_level"))) {
                if ("0004".equals(map.get("sensor_type"))) {
                    itemYellow.setCo((Long) map.get("count"));
                } else {
                    itemYellow.setCh4((Long) map.get("count"));
                }
            } else if ("橙色预警".equals(map.get("alram_level"))) {
                if ("0004".equals(map.get("sensor_type"))) {
                    itemOrange.setCo((Long) map.get("count"));
                } else {
                    itemOrange.setCh4((Long) map.get("count"));
                }
            } else if ("红色预警".equals(map.get("alram_level"))) {
                if ("0004".equals(map.get("sensor_type"))) {
                    itemRed.setCo((Long) map.get("count"));
                } else {
                    itemRed.setCh4((Long) map.get("count"));
                }
            }
        }
        monitorTodayInfo.setBlue(itemBlue);
        monitorTodayInfo.setOrange(itemOrange);
        monitorTodayInfo.setYellow(itemYellow);
        monitorTodayInfo.setRed(itemRed);
        return monitorTodayInfo;
    }

    @Override
    public List<KeyAreasVo> keyAreas(String areaId, String mineCode) {
        String sql = "SELECT t.point_location as name,t.point_value as value,t.value_unit as unit FROM" +
                " \"dwd_aqjk_now_sensormonitor\" t join dwd_aqjk_now_base_sensorinfo tt on (t.point_code=tt.point_code) " +
                " where  tt.is_important='1' %s   %s" +
                " and data_time=(select max(data_time) from dwd_aqjk_now_sensormonitor) order by tt.point_value_type desc,tt.sensor_type";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and t.mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        if (StringUtils.isNotBlank(areaId)) {
            areaId = " and tt.workface_code='" + areaId + "'";
        } else {
            areaId = "";
        }
        List<KeyAreasVo> keyAreasVos = monitorJdbcTemplate.query(String.format(sql, areaId, mineCode), new BeanPropertyRowMapper<>(KeyAreasVo.class));
        if (!keyAreasVos.isEmpty()) {
            Map<String, String> aqjk_loaction_name = getDict("aqjk_loaction_name");
            keyAreasVos.forEach(s -> {
                if (aqjk_loaction_name.get(s.getName()) != null) s.setName(aqjk_loaction_name.get(s.getName()));
            });
        }

        return keyAreasVos;
    }

    @Override
    public AlarmTrendVo alarmTrend(String mineCode, String type) {
        Calendar calendar = Calendar.getInstance();
        Date endTime = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<String> xdata = new ArrayList<>();
        if (type.equals("周")) {
            calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 7);
        } else {
            calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
        }
        while (calendar.getTime().getTime() <= endTime.getTime()) {
            xdata.add(sdf.format(calendar.getTime()));
            calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) + 1);
        }
        String sql = "SELECT to_char(end_time,'yyyy-mm-dd') as day,sensor_type,count(1) as count " +
                "FROM \"dwd_aqjk_now_sensoralarm_count_stat\" " +
                "where   (sensor_type = '0004' or  sensor_type='0001') and " +
                "end_time is not null  and max_value  is not  null " +
                "and end_time>'%s' and outlier_type='001' %s " +
                "GROUP BY day,sensor_type";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        long[] co = new long[xdata.size()];
        long[] ch4 = new long[xdata.size()];
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql, xdata.get(0), mineCode));
        for (Map<String, Object> map : maps) {
            if (map.get("sensor_type").equals("0004")) {
                co[xdata.indexOf(map.get("day"))] = (Long) map.get("count");
            } else {
                ch4[xdata.indexOf(map.get("day"))] = (Long) map.get("count");
            }
        }
        AlarmTrendVo alarmTrendVo = new AlarmTrendVo();
        alarmTrendVo.setXData(xdata.toArray(new String[xdata.size()]));
        alarmTrendVo.setCh4(ch4);
        alarmTrendVo.setCo(co);
        return alarmTrendVo;
    }

    @Override
    public List<SafetyMonitorVo> safetyMonitor(String mineCode) {
        String sql = "SELECT point_code as code,sensor_type_name as type,point_location as addr,point_value as value, " +
                "value_unit as unit,point_status as status ,data_time as date " +
                "FROM dwd_aqjk_now_sensormonitor " +
                "where data_time=(select max(data_time) from dwd_aqjk_now_sensormonitor) %s";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        //单位null赋值
        List<SafetyMonitorVo> list = monitorJdbcTemplate.query(String.format(sql, mineCode), new BeanPropertyRowMapper<>(SafetyMonitorVo.class));
        for (SafetyMonitorVo safetyMonitorVo : list) {
            if (safetyMonitorVo.getUnit() == null) {
                safetyMonitorVo.setUnit("");
            }
        }
        return list;
    }

    @Override
    public List<PointStatistics> pointStatistics(String mineCode) {
        String sql = "SELECT t.sensor_type_name as type,COUNT(1) as pointCount,SUM(case t.point_status when '0' then 0  when '256' then 0 else 1 end) as alarmCount FROM \"dwd_aqjk_now_sensormonitor\" \n" +
                "t join dwd_aqjk_now_base_sensorinfo tt on (t.point_code=tt.point_code) where  " +
                " data_time=(select max(data_time) from dwd_aqjk_now_sensormonitor) and tt.sensor_type in ('0001','0004','0002','0014','0003','1008','0012','0018') %s GROUP BY T.sensor_type_name";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and t.mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        return monitorJdbcTemplate.query(String.format(sql, mineCode), new BeanPropertyRowMapper<>(PointStatistics.class));
    }

    @Override
    public Indicator indicator(String mineCode) {
        String sql = "SELECT data_time FROM \"dwd_aqjk_now_sensormonitor\" " +
                "where data_time>current_timestamp - interval '10 minutes' %s limit 1";
        R<MineVo> r = remoteMineInfoService.getMineInfo(mineCode);
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        List list = monitorJdbcTemplate.queryForList(String.format(sql, mineCode));
        Indicator indicator = new Indicator();
        indicator.setStatus(list.isEmpty() ? "断开" : "正常");
        RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true);

        if (Constants.SUCCESS == r.getCode()) {
            indicator.setGasGrade(r.getData().getGasLevel() + "");
            indicator.setCombustion(r.getData().getCoalDustPyrophoric());
            indicator.setExplosive(r.getData().getCoalDustExplosion());
        }
        R<SysModelVo> sys = remoteMineInfoService.getSysModel("安全监控");
        if (Constants.SUCCESS == sys.getCode()) indicator.setModel(sys.getData().getSysModel());

        return indicator;
    }

    @Override
    public AlarmTrendVo indexAlarmTrend(String type, String mineCode) {
        AlarmTrendVo alarmTrendVo = new AlarmTrendVo();
        Calendar calendar = Calendar.getInstance();
        Date endTime = calendar.getTime();
        if ("月".equals(type)) {
            calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
        } else {
            calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 7);
        }
        List<String> xDate = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        while (calendar.getTime().getTime() <= endTime.getTime()) {
            xDate.add(sdf.format(calendar.getTime()));
            calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) + 1);
        }
        alarmTrendVo.setXData(xDate.toArray(new String[xDate.size()]));
        String sql = "SELECT to_char(end_time,'yyyy-mm-dd') as day,sensor_type,count(1) as count " +
                "FROM \"dwd_aqjk_now_sensoralarm_count_stat\" " +
                "where   (sensor_type = '0004' or  sensor_type='0001') %s " +
                " and end_time is not null  and max_value  is not  null " +
                "and end_time>'%s' and outlier_type='001' " +
                "GROUP BY day,sensor_type";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql, mineCode, xDate.get(0)));
        long[] co = new long[xDate.size()];
        long[] ch4 = new long[xDate.size()];
        for (Map<String, Object> map : maps) {
            if (map.get("sensor_type").equals("0004")) {
                co[xDate.indexOf(map.get("day"))] = (Long) map.get("count");
            } else {
                ch4[xDate.indexOf(map.get("day"))] = (Long) map.get("count");
            }
        }
        alarmTrendVo.setCh4(ch4);
        alarmTrendVo.setCo(co);
        return alarmTrendVo;
    }


    public List<String> getWorkFace(String mineCode) {
        if ("150621011038".equals(mineCode)) {
            List<String> list = new ArrayList<>();
            list.add("204");
            list.add("301");
            list.add("108");
            list.add("202");
            return list;
        }
        String sql = "SELECT workface_code FROM \"dwd_aqjk_now_base_sensorinfo\" where workface_code is not null %s GROUP BY workface_code ORDER BY workface_code";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        return monitorJdbcTemplate.queryForList(String.format(sql, mineCode), String.class);
    }

    @Override
    public ResponsePage<SensorAlarmEntity> sensorAlarmPage(Pageable pageable, String sensorType, String outlierType, String beginTime, String endTime, String mineCode) {
        SensorAlarmEntity entity = new SensorAlarmEntity();
        entity.setMineCode(mineCode);
        if (StringUtils.isNotBlank(sensorType)) {
            entity.setSensorType(sensorType);
        }
        if (StringUtils.isNotBlank(outlierType)) {
            entity.setOutlierType(outlierType);
        }
        StringBuilder sb = new StringBuilder(" ");
        if (StringUtils.isNotBlank(beginTime)) {
            sb.append(" and  dataTime >='").append(beginTime).append("' ");
        }
        if (StringUtils.isNotBlank(endTime)) {
            sb.append(" and dataTime <='").append(endTime).append("' ");
        }
        ResponsePage<SensorAlarmEntity> page = HqlUtils.findPage(monitorEntityManager, entity,
                pageable, sb.toString(), Sort.by(Sort.Direction.DESC, "dataTime"));
        page.getPageData().forEach(s -> {
            if (s.getBeginTime() != null && s.getEndTime() != null) {
                s.setDuration((s.getEndTime().getTime() - s.getBeginTime().getTime()) / 1000);
            }
        });
        return page;
    }

    @Override
    public ResponsePage<AqjkNowSensorMonitorEntity> sensorMonitorNow(Pageable pageable, String pointLocation, String sensorType, String status, String mineCode) {
        AqjkNowSensorMonitorEntity entity = new AqjkNowSensorMonitorEntity();
        entity.setMineCode(mineCode);
        if (StringUtils.isNotBlank(sensorType)) {
            entity.setSensorType(sensorType);
        }
        if (StringUtils.isNotBlank(status)) {
            entity.setPointStatus(status);
        }
        String pointLocationString = "";
        String and = "";
        if (StringUtils.isNotBlank(pointLocation)) {
            if (StringUtils.isNotBlank(sensorType) || StringUtils.isNotBlank(status) || StringUtils.isNotBlank(mineCode)) {
                and = " and ";
            }
            pointLocationString = and + "point_location like '%" + pointLocation + "%'";
        }

        ResponsePage<AqjkNowSensorMonitorEntity> page = HqlUtils.findPage(monitorEntityManager, entity,
                pageable, pointLocationString, Sort.by(Sort.Direction.DESC, "dataTime"));
        return page;
    }

    @Override
    public ResponsePage<AqjkHisSensorMonitorEntity> sensorMonitorHis(Pageable pageable, String sensorType, String beginTime, String endTime, String loaction, String mineCode) {
        AqjkHisSensorMonitorEntity entity = new AqjkHisSensorMonitorEntity();
        entity.setMineCode(mineCode);
        if (StringUtils.isNotBlank(sensorType)) {
            entity.setSensorType(sensorType);
        }
        StringBuilder sb = new StringBuilder(" ");
        if (StringUtils.isNotBlank(beginTime)) {
            sb.append(" and  dataTime >='").append(beginTime).append("' ");
        }
        if (StringUtils.isNotBlank(endTime)) {
            sb.append(" and dataTime <='").append(endTime).append("' ");
        }
        if (StringUtils.isNotBlank(loaction)) {
            sb.append(" and pointLocation like '%").append(loaction).append("%' ");
        }
        ResponsePage<AqjkHisSensorMonitorEntity> page = HqlUtils.findPage(monitorEntityManager, entity,
                pageable, sb.toString(), Sort.by(Sort.Direction.DESC, "dataTime"));

        return page;
    }

    @Override
    public List<AqjkHisSensorMonitorEntity> findByPointCodeAndDataTimeBetween(String pointCode, Date beginTime, Date endTime, String mineCode) {
        if (beginTime == null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(endTime);
            calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 1);
            endTime = calendar.getTime();//Between不包含结束时间 所以加一秒
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 6);
            beginTime = calendar.getTime();
        }
        List<AqjkHisSensorMonitorEntity> byPointCodeAndDataTimeBetween;
        if (net.hn.hnms.sys.common.core.utils.StringUtils.isBlank(mineCode)) {
            byPointCodeAndDataTimeBetween = aqjkHisSensorMonitorRepository.findByPointCodeAndDataTimeBetweenOrderByDataTime(pointCode, beginTime, endTime);

        } else {
            byPointCodeAndDataTimeBetween = aqjkHisSensorMonitorRepository.findByPointCodeAndDataTimeBetweenAndMineCode(pointCode, beginTime, endTime, mineCode);
        }
//        ChartVo chartVo = new ChartVo();
//        chartVo.setValeus(new ArrayList<>());
//        chartVo.setXData(new ArrayList<>());
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (byPointCodeAndDataTimeBetween.size() > 0) {
            Map<String, String> point_status = getDict("point_status");
            byPointCodeAndDataTimeBetween.forEach(s -> {
                s.setPointStatus(point_status.get(s.getPointStatus()));
            });
        }
        return byPointCodeAndDataTimeBetween;
    }

    @Override
    public ResponsePage<AqjkNowBaseSensorinfoEntity> baseSensorInfo(Pageable pageable, String sensorType, String location, boolean currentValue, String mineCode) {
        AqjkNowBaseSensorinfoEntity entity = new AqjkNowBaseSensorinfoEntity();
        entity.setMineCode(mineCode);
        if (StringUtils.isNotBlank(sensorType)) {
            entity.setSensorType(sensorType);
        }
        StringBuilder sb = new StringBuilder(" ");
        if (StringUtils.isNotBlank(location)) {
            sb.append(" and  pointMonitorLocation like '%").append(location).append("%' ");
        }

        ResponsePage<AqjkNowBaseSensorinfoEntity> page = HqlUtils.findPage(monitorEntityManager, entity,
                pageable, "");
        if (currentValue && !page.getPageData().isEmpty()) {
            List<String> collect = page.getPageData().stream().map(AqjkNowBaseSensorinfoEntity::getPointCode).collect(Collectors.toList());
            String sql = "SELECT point_code,\n" +
                    "(select point_value from dwd_aqjk_now_sensormonitor where data_time=max(t1.data_time) and point_code=t1.point_code limit 1)\n" +
                    "FROM \"dwd_aqjk_now_sensormonitor\" t1\n" +
                    "where point_code in ('%s') \n" +
                    "GROUP BY point_code ";
            List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql, StringUtils.join(collect, "','")));
            Map<Object, Object> vlausMap = maps.stream().collect(Collectors.toMap(s -> s.get("point_code"), s -> s.get("point_value")));
            page.getPageData().forEach(s -> {
                if (vlausMap.get(s.getPointCode()) != null) {
                    s.setCurrentValue(vlausMap.get(s.getPointCode()).toString());
                }
            });
        }

        return page;
    }

    @Override
    public SensorValueTrendVo trendBySensorCode(String sensorCode, String mineCode) {
        Calendar calendar = Calendar.getInstance();
        Date endTime = calendar.getTime();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 7);
        List<String> xDate = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        while (calendar.getTime().getTime() <= endTime.getTime()) {
            xDate.add(sdf.format(calendar.getTime()));
            calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) + 1);
        }
        String sql = "SELECT to_char(data_time,'yyyy-mm-dd') as day,max(point_value) as max,min(point_value) as min FROM \"dwd_aqjk_his_sensormonitor\" where point_code='%s' and data_time>='%s' %s GROUP BY day  ORDER BY day";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql, sensorCode, xDate.get(0), mineCode));
        SensorValueTrendVo vo = new SensorValueTrendVo();
        String[] max = new String[xDate.size()];
        String[] min = new String[xDate.size()];
        vo.setXData(xDate);
//        vo.setMaxValue();
//        vo.setMinValue(new ArrayList<>());
        maps.forEach(s -> {
            max[xDate.indexOf(s.get("day"))] = s.get("max") + "";
            min[xDate.indexOf(s.get("day"))] = s.get("min") + "";
        });
        vo.setMinValue(Arrays.asList(min));
        vo.setMaxValue(Arrays.asList(max));
        return vo;
    }

    /**
     * 传感器异常数据记录列表
     *
     * @param pointCode
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    public List<SensorAlarmEntity> pointExceptionRecordDataList(String pointCode, Date beginTime, Date endTime, String mineCode) {
        if (beginTime == null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(endTime);
            calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) + 1);
            endTime = calendar.getTime();//Between不包含结束时间 所以加一秒
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 6);
            beginTime = calendar.getTime();
        }
        List<SensorAlarmEntity> list;
        if (StringUtils.isBlank(mineCode)) {
            list = sensorAlarmEntityRepository.findByPointCodeAndDataTimeBetweenOrderByDataTime(pointCode, beginTime, endTime);
        } else {
            list = sensorAlarmEntityRepository.findByPointCodeAndDataTimeBetweenAndMineCodeOrderByDataTime(pointCode, beginTime, endTime, mineCode);
        }

        list.forEach(s -> {
            if (s.getBeginTime() != null && s.getEndTime() != null) {
                s.setDuration((s.getEndTime().getTime() - s.getBeginTime().getTime()) / 1000);
            }
        });
        return list;
    }

    public Map<String, String> getDict(String type) {
        Map<String, String> collect = RedisUtils.getCacheObject(type);
        if (collect == null || collect.isEmpty()) {
            String sql = "SELECT point_loaction_name,simple_name FROM \"aqjk_dict\" where \"type\"='%s'";
            collect = monitorJdbcTemplate.queryForList(String.format(sql, type)).stream().collect(Collectors.toMap(s -> "" + s.get("point_loaction_name"), s -> "" + s.get("simple_name")));
            RedisUtils.setCacheObject(type, collect, Duration.ofMinutes(10l));
        }
        return collect;
    }

    public List<SafetyMonitorVo> environmentalAwareness(Double x, Double y, Double z, String mineCode) {
        List<String> codes = null;
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        if (x != null && y != null & z != null) {
            String subStationCodSql = "SELECT point_code  FROM \"dwd_aqjk_now_base_sensorinfo\" where sqrt(power(%s-x_coordinate, 2)+power(%s-y_coordinate, 2)+power(%s-z_coordinate, 2))<1000";
            codes = monitorJdbcTemplate.queryForList(String.format(subStationCodSql, x, y, z, mineCode), String.class);
        }
        StringBuilder sql = new StringBuilder("SELECT point_code as code,sensor_type_name as type,point_location as addr,point_value as value, " +
                "value_unit as unit,point_status as status ,data_time as date " +
                "FROM dwd_aqjk_now_sensormonitor " +
                "where data_time=(select max(data_time) from dwd_aqjk_now_sensormonitor) %s");
        if (codes != null) {
            sql.append(" and point_code in ('").append(StringUtils.join(codes, "','")).append("') ");
        }
        List<SafetyMonitorVo> list = monitorJdbcTemplate.query(String.format(sql.toString(), mineCode), new BeanPropertyRowMapper<>(SafetyMonitorVo.class));
        return list;
    }

    @Override
    public SubsidenceAnalysisVo concentration(String[] pointCodes, String mineCode) {
        List<String> xDate = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("HH");
        for (int i = 0; i < 24; i++) {
            xDate.add(sdf.format(calendar.getTime()));
            calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
        }
        Collections.reverse(xDate);
        Map<String, BigDecimal[]> valueMap = new HashMap<>();
        for (String pointCode : pointCodes) {
            valueMap.put(pointCode, new BigDecimal[xDate.size()]);
        }
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH");
        String sql = "SELECT to_char(data_time,'hh24') as houre,max(point_value) as value, max(point_location) as location,point_code" +
                " FROM \"dwd_aqjk_his_sensormonitor\" where  data_time > to_timestamp('%s','yyyy-MM-dd hh24')  and point_code in ('%s') %s GROUP BY to_char(data_time,'hh24'),point_code";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql, sdf2.format(calendar.getTime()), StringUtils.join(pointCodes, "','"), mineCode));
        Map<String, String> pointNameMap = new HashMap<>();
        maps.forEach(s -> {
            pointNameMap.put(s.get("point_code").toString(), s.get("location") + "");
            valueMap.get(s.get("point_code"))[xDate.indexOf(s.get("houre"))] = new BigDecimal(s.get("value").toString());
        });
        SubsidenceAnalysisVo vo = new SubsidenceAnalysisVo();
        vo.setXDate(xDate.toArray(new String[xDate.size()]));
        vo.setYdataList(new ArrayList<>());
        for (Map.Entry<String, BigDecimal[]> entry : valueMap.entrySet()) {
            String key = entry.getKey();
            BigDecimal[] value = entry.getValue();

            SubsidenceAnalysisVo.Ydata ydata = vo.new Ydata();
            ydata.setName(pointNameMap.get(key));
            ydata.setYdata(value);
            vo.getYdataList().add(ydata);
        }
        return vo;
    }

    @Override
    public PointStatus pointStatus(String workFace, String mineCode) {
        StringBuilder numberSql = new StringBuilder("SELECT count(*) FROM \"dwd_aqjk_now_base_sensorinfo\"");
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        PointStatus pointStatus = new PointStatus();
        if (StringUtils.isNotBlank(workFace)) {
            numberSql.append(" where workface_code ='").append(workFace).append("'  %s ");
        }
        pointStatus.setNumber(monitorJdbcTemplate.queryForObject(String.format(numberSql.toString(), mineCode), Integer.class));
        StringBuilder onlineSql = new StringBuilder("SELECT count(*) FROM \"dwd_aqjk_now_sensormonitor\" t where data_time=(select max(data_time) from dwd_aqjk_now_sensormonitor) %s");
        if (StringUtils.isNotBlank(workFace)) {
            onlineSql.append(" and EXISTS (select 1 from dwd_aqjk_now_base_sensorinfo where point_code=t.point_code and workface_code='").append(workFace).append("') ");
        }
        Integer online = monitorJdbcTemplate.queryForObject(String.format(onlineSql.toString(), mineCode), Integer.class);
        pointStatus.setOnline(online > pointStatus.getNumber() ? pointStatus.getNumber() : online);
        pointStatus.setBreakOff(pointStatus.getNumber() - pointStatus.getOnline());
        StringBuilder chaoxianSql = new StringBuilder("SELECT count(*) FROM \"dwd_aqjk_now_sensoralarm\" t" +
                " where outlier_type='001'  and sensor_type = '%s'  %s  and data_time> now()::timestamp + '-3 min' ");
        if (StringUtils.isNotBlank(workFace)) {
            chaoxianSql.append(" and EXISTS (select 1 from dwd_aqjk_now_base_sensorinfo where point_code=t.point_code and workface_code='").append(workFace).append("') ");
        }
        pointStatus.setCH4(monitorJdbcTemplate.queryForObject(String.format(chaoxianSql.toString(), "0001", mineCode), Integer.class));
        pointStatus.setCO(monitorJdbcTemplate.queryForObject(String.format(chaoxianSql.toString(), "0004", mineCode), Integer.class));
        return pointStatus;
    }

    @Override
    public SubsidenceAnalysisVo gushTrend() {
        String sql = "SELECT * FROM \"dws_sensor_pred_data\" where data_flag=1 and data_time>CURRENT_TIMESTAMP order by data_time  ";
        Map<String, String[]> map = new HashMap<>();
        List<String> xdate = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm");
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(sql);
        maps.forEach(s -> {
            String data_time = sdf.format(s.get("data_time"));
            if (!xdate.contains(data_time)) {
                xdate.add(data_time);
            }
        });
        maps.forEach(s -> {
            String coalface_name = s.get("coalface_name").toString();
            String data_time = sdf.format(s.get("data_time"));
            if (map.get(coalface_name) != null) {
                String[] strings = map.get(coalface_name);
                strings[xdate.indexOf(data_time)] = s.get("sensor_value").toString();
            } else {
                String[] strings = new String[xdate.size()];
                strings[xdate.indexOf(data_time)] = s.get("sensor_value").toString();
                map.put(coalface_name, strings);
            }
        });
        SubsidenceAnalysisVo vo = new SubsidenceAnalysisVo();
        vo.setXDate(xdate.toArray(new String[xdate.size()]));
        for (Map.Entry<String, String[]> entry : map.entrySet()) {
            SubsidenceAnalysisVo.Ydata ydata = vo.new Ydata();
            ydata.setName(entry.getKey());
            BigDecimal[] array = new BigDecimal[entry.getValue().length];
            for (int i = 0; i < entry.getValue().length; i++) {
                array[i] = new BigDecimal(entry.getValue()[i]);
            }
            ydata.setYdata(array);
            vo.getYdataList().add(ydata);
        }
        return vo;
    }

    @Override
    public SubsidenceAnalysisVo coalEarlyWarning() {
        List<String> xDate = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("HH");
        for (int i = 0; i <= 12; i++) {
            xDate.add(sdf.format(calendar.getTime()));
            if (i != 12) {
                calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
            }
        }
        Collections.reverse(xDate);
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH");
        String sql = "SELECT area_code,to_char(data_time,'hh24') sj,max(alarm_type) as alarm_type  FROM \"dws_coal_spontaneous_combustion_alarm\" where data_time> to_timestamp('%s','yyyy-MM-dd hh24') GROUP BY area_code,sj";
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql, sdf2.format(calendar.getTime())));
//        Map<String, String> pointNameMap = new HashMap<>();
        Map<String, BigDecimal[]> valueMap = new HashMap<>();
        maps.forEach(s -> {
//            pointNameMap.put(s.get("area_code").toString(), s.get("area_code") + "");
            if (valueMap.get(s.get("area_code")) == null) {
                valueMap.put(s.get("area_code").toString(), new BigDecimal[xDate.size()]);
            }
            valueMap.get(s.get("area_code"))[xDate.indexOf(s.get("sj"))] = new BigDecimal(s.get("alarm_type").toString());
        });
        SubsidenceAnalysisVo vo = new SubsidenceAnalysisVo();
        vo.setXDate(xDate.toArray(new String[xDate.size()]));
        vo.setYdataList(new ArrayList<>());
        for (Map.Entry<String, BigDecimal[]> entry : valueMap.entrySet()) {
            String key = entry.getKey();
            BigDecimal[] value = entry.getValue();

            SubsidenceAnalysisVo.Ydata ydata = vo.new Ydata();
            ydata.setName(key);
            ydata.setYdata(value);
            vo.getYdataList().add(ydata);
        }
        return vo;
    }

    public List<AlarmMessageItemVo> alarmMessageItem(String mineCode) {

        String sql = "SELECT  " +
                "		CASE sensor_type " +
                "			WHEN  '0004'  " +
                "			then " +
                "				case  " +
                "					when  extract(epoch FROM ( end_time- begin_time ))<=900  " +
                "					then  " +
                "						case  " +
                "							when (max_value<50 and max_value>=24) then '蓝色预警' " +
                "							when (max_value<90 and max_value>=50) then '蓝色预警' " +
                "							when (max_value<200 and max_value>=90) then '黄色预警' " +
                "							when ( max_value>=200) then '橙色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))<=1500 and  extract(epoch FROM ( end_time- begin_time ))>900 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<50 and max_value>=24) then '蓝色预警' " +
                "							when (max_value<90 and max_value>=50) then '黄色预警' " +
                "							when (max_value<200 and max_value>=90) then '黄色预警' " +
                "							when ( max_value>=200) then '橙色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))<=1800 and  extract(epoch FROM ( end_time- begin_time ))>1500 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<50 and max_value>=24) then '黄色预警' " +
                "							when (max_value<90 and max_value>=50) then '黄色预警' " +
                "							when (max_value<200 and max_value>=90) then '橙色预警' " +
                "							when ( max_value>=200) then '红色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))>1800 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<50 and max_value>=24) then '黄色预警' " +
                "							when (max_value<90 and max_value>=50) then '橙色预警' " +
                "							when (max_value<200 and max_value>=90) then '红色预警' " +
                "							when ( max_value>=200) then '红色预警'  " +
                "						end " +
                "				end " +
                "			WHEN  '0001'  " +
                "			then " +
                "				case  " +
                "					when  extract(epoch FROM ( end_time- begin_time ))<=900  " +
                "					then  " +
                "						case  " +
                "							when (max_value<1 and max_value>=0.5) then '蓝色预警' " +
                "							when (max_value<1.5 and max_value>=1) then '蓝色预警' " +
                "							when (max_value<2 and max_value>=1.5) then '黄色预警' " +
                "							when ( max_value>=2) then '橙色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))<=1500 and  extract(epoch FROM ( end_time- begin_time ))>900 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<1 and max_value>=0.5) then '蓝色预警' " +
                "							when (max_value<1.5 and max_value>=1) then '黄色预警' " +
                "							when (max_value<2 and max_value>=1.5) then '黄色预警' " +
                "							when ( max_value>=2) then '橙色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))<=1800 and  extract(epoch FROM ( end_time- begin_time ))>1500 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<1 and max_value>=0.5) then '黄色预警' " +
                "							when (max_value<1.5 and max_value>=1) then '黄色预警' " +
                "							when (max_value<2 and max_value>=1.5) then '橙色预警' " +
                "							when ( max_value>=2) then '红色预警'  " +
                "						end " +
                "					when extract(epoch FROM ( end_time- begin_time ))>1800 " +
                "					then " +
                "						case " +
                "							WHEN (max_value<1 and max_value>=0.5) then '黄色预警' " +
                "							when (max_value<1.5 and max_value>=1) then '橙色预警' " +
                "							when (max_value<2 and max_value>=1.5) then '红色预警' " +
                "							when ( max_value>=2) then '红色预警'  " +
                "						end " +
                "				end " +
                "		END as alramLevel, " +
                "		sensor_type,begin_time," +
                "		point_location " +
                "FROM     dwd_aqjk_now_sensoralarm_count_stat  " +
                "where   (sensor_type = '0004' or  sensor_type='0001') and end_time is not null  and max_value  is not  null %s " +
                "AND ( end_time > ( current_timestamp  - interval '30 minutes') OR begin_time >  (current_timestamp  - interval '30 minutes') ) ";
        if (StringUtils.isNotBlank(mineCode)) {
            mineCode = " and mine_code='" + mineCode + "'";
        } else {
            mineCode = "";
        }
        //sensor_type 0001 环境瓦斯   0004 一氧化碳      outlier_type 001超限报警
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(String.format(sql, mineCode));
        List<AlarmMessageItemVo> list = new ArrayList<>();
        for (Map<String, Object> map : maps) {
            AlarmMessageItemVo messageItemVo = new AlarmMessageItemVo();
            messageItemVo.setAlarmTime((Date) map.get("begin_time"));
            messageItemVo.setAlarmType("安全监控");
            messageItemVo.setContent(map.get("point_location") + "发生超限" + map.get("alramLevel"));
            messageItemVo.setKey("aqjk_" + map.get("id"));
            messageItemVo.setAlarmLevel(map.get("alramLevel") + "");
            if ("0001".equals(map.get("sensor_type"))) {
                messageItemVo.setSensorType("瓦斯");
            } else if ("0004".equals(map.get("sensor_type"))) {
                messageItemVo.setSensorType("一氧化碳");
            }
            list.add(messageItemVo);
        }
        return list;
    }

    @Override
    public List<DataStateVo> getMaxTime(String mineCode, String companyCode) {
        String sql = "SELECT mine_code as mineCode,max(data_time) as maxTime  FROM dwd_aqjk_now_sensormonitor where 1=1 %s %s group by mine_code";
        if (StringUtils.isNotBlank(mineCode)) {
            //优化查询语句
            sql = sql.replaceFirst("mine_code", "'" + mineCode + "'");
            sql = sql.replace("group by mine_code", "");
            mineCode = "and mine_code='" + mineCode + "' ";

        } else {
            mineCode = "";
        }
        if (StringUtils.isNotBlank(companyCode) && StringUtils.isBlank(mineCode)) {
            companyCode = "and company_code='" + companyCode + "' ";
        } else {
            companyCode = "";
        }
        List<DataStateVo> query = monitorJdbcTemplate.query(String.format(sql, mineCode, companyCode), new BeanPropertyRowMapper<>(DataStateVo.class));
        return query;
    }

    /**
     * 根据工作面获取重点区域信息
     *
     * @param workFaceName
     * @param mineCode
     * @return
     */
    @Override
    public List<keyAreasVo> getkeyAreasInfoByWorkFace(String workFaceName, String mineCode) {
        if (StringUtils.isEmpty(workFaceName)) {
            //工作面名称为空
            throw new HuaNengException(Constants.FAIL, "工作面名称不能为空");
        }
        LambdaQueryWrapper<SensorImportanceConfigPo> queryWrapper = new LambdaQueryWrapper<>();
        //工作面名称
        queryWrapper.eq(SensorImportanceConfigPo::getWorkName, workFaceName);
        //煤矿编码
        queryWrapper.eq(StringUtils.isNotBlank(mineCode), SensorImportanceConfigPo::getMineCode, mineCode);
        //升序查询
        queryWrapper.orderByAsc(SensorImportanceConfigPo::getSensorOrder);
        List<SensorImportanceConfigPo> sensorImportanceConfigPos = sensorImportanceConfigMapper.selectList(queryWrapper);
        if (sensorImportanceConfigPos.isEmpty()) {
            int insert = 0;
            //查询不到工作面信息 生成默认信息
            for (int i = 0; i < 6; i++) {
                SensorImportanceConfigPo sensorImportanceConfigPo = new SensorImportanceConfigPo();
                //默认工作面为前端传递过来的工作面
                sensorImportanceConfigPo.setWorkName(workFaceName);
                //序号为1-6
                sensorImportanceConfigPo.setSensorOrder(i);
                //传感器类型
                sensorImportanceConfigPo.setSensorOrder(i);
                if (i == 0) {
                    sensorImportanceConfigPo.setSensorTypeName(getKeyAreasType("温度"));
                } else if (i == 1) {
                    sensorImportanceConfigPo.setSensorTypeName(getKeyAreasType("一氧化碳"));

                } else if (i == 2 || 2 == 3 || i == 4) {
                    sensorImportanceConfigPo.setSensorTypeName(getKeyAreasType("甲烷"));
                } else {
                    sensorImportanceConfigPo.setSensorTypeName(getKeyAreasType("风速"));

                }
                //煤矿编码
                sensorImportanceConfigPo.setMineCode(mineCode);
                insert += sensorImportanceConfigMapper.insert(sensorImportanceConfigPo);
            }
            if (insert != 6) {
                throw new HuaNengException(Constants.FAIL, "查询到未知工作面，初始化记录异常");
            }
        }
        sensorImportanceConfigPos = sensorImportanceConfigMapper.selectList(queryWrapper);
        List<keyAreasVo> collect = sensorImportanceConfigPos.stream().map(t -> {

            keyAreasVo keyAreasVo = new keyAreasVo();
//            //查询Base测点最新记录
//            BaseSensorInfoNowPo baseSensorInfoNowPo = baseSensorInfoNowMapper.selectOne(new LambdaQueryWrapper<BaseSensorInfoNowPo>().eq(BaseSensorInfoNowPo::getPointCode, t.getPointCode()).eq(StringUtils.isNotBlank(mineCode), BaseSensorInfoNowPo::getMineCode, mineCode));
//            if (baseSensorInfoNowPo == null) {
//                //测点编码
//                keyAreasVo.setPointCode(null);
//                //测点所属位置
//                keyAreasVo.setLocation(null);
//                //测点值
//                keyAreasVo.setValue(null);
//                //测点单位
//                keyAreasVo.setUnit(null);
//                //别名
//                keyAreasVo.setName(null);
//                //测点序号
//                keyAreasVo.setNumber(t.getSensorOrder());
//                //类型名称
//                keyAreasVo.setPointTypeName(t.getSensorTypeName());
//            } else {
            //测点编码
            keyAreasVo.setPointCode(t.getPointCode());
            //测点所属位置
//                keyAreasVo.setLocation(baseSensorInfoNowPo.getPointMonitorLocation());
            keyAreasVo.setLocation(t.getPointMonitorLocation());
            //获取测点实时表中数据
            SensorMonitorNowPo sensorMonitorNowPo = sensorMonitorNowMapper.selectOne(new LambdaQueryWrapper<SensorMonitorNowPo>()
                    .eq(StringUtils.isNotBlank(t.getMineCode()), SensorMonitorNowPo::getMineCode, t.getMineCode())
                    .eq(SensorMonitorNowPo::getPointCode, t.getPointCode()).orderByDesc(SensorMonitorNowPo::getDataTime).last("LIMIT 1"));
            if (sensorMonitorNowPo == null) {
                //测点值
                keyAreasVo.setValue(null);
            } else {
                keyAreasVo.setValue(new BigDecimal(sensorMonitorNowPo.getPointValue()).setScale(2, BigDecimal.ROUND_HALF_UP));
                //测点单位
                keyAreasVo.setUnit(sensorMonitorNowPo.getValueUnit());
            }
            //别名
            //判断是否为空，如果为空则使用location,如果不为空则使用别名
            if (StringUtils.isEmpty(t.getLocationAlias())) {
                //是空的
                keyAreasVo.setName(t.getPointMonitorLocation());
            } else {
                keyAreasVo.setName(t.getLocationAlias());
            }
            //测点序号
            keyAreasVo.setNumber(t.getSensorOrder());
            //类型名称
            keyAreasVo.setPointTypeName(t.getSensorTypeName());
//            }
            return keyAreasVo;
        }).collect(Collectors.toList());

        return collect;
    }

    /**
     * 根据测点类型获取所有测点
     *
     * @param pointTypeName
     * @param mineCode
     * @return
     */
    @Override
    public List<PointListVO> getPointListByPointType(String pointTypeName, String mineCode) {
        if (StringUtils.isEmpty(pointTypeName)) {
            //测点类型名称
            throw new HuaNengException(Constants.FAIL, "测点类型名称不能为空");
        }
//        LambdaQueryWrapper<BaseSensorInfoNowPo> queryWrapper = new LambdaQueryWrapper<>();
//        //测点类型名称
//        queryWrapper.eq(BaseSensorInfoNowPo::getSensorTypeName, pointTypeName);
//        //煤矿编码
//        queryWrapper.eq(StringUtils.isNotBlank(mineCode), BaseSensorInfoNowPo::getMineCode, mineCode);
        //根据类型查询出所有的base测点信息
//        List<BaseSensorInfoNowPo> baseSensorInfoNowPos = baseSensorInfoNowMapper.selecBasetList(mineCode,pointTypeName);
        //直接查询当前类型得now表类型信息
        List<SensorMonitorNowPo> sensorMonitorNowPos = sensorMonitorNowMapper.selectTypeList(mineCode, pointTypeName);
        if (sensorMonitorNowPos.isEmpty()) {
            throw new HuaNengException(Constants.FAIL, "未查到任何测点信息");
        }
        //根据测点编码查询所有的实时信息
        //过滤筛选  base存在测点而实时表不存在测点则剔除
//        baseSensorInfoNowPos = baseSensorInfoNowPos.stream()
//                .filter(baseSensorInfoNowPo -> {
//                    List<SensorMonitorNowPo> sensorMonitorNowPos = sensorMonitorNowMapper.selectList(new LambdaQueryWrapper<SensorMonitorNowPo>()
//                            .eq(StringUtils.isNotBlank(mineCode), SensorMonitorNowPo::getMineCode, mineCode)
//                            .eq(SensorMonitorNowPo::getPointCode, baseSensorInfoNowPo.getPointCode()));
//                    //记录不为空
//                    if (!sensorMonitorNowPos.isEmpty()) {
//                        return true;
//                    } else {
//                        return false;
//                    }
//                })
//                .collect(Collectors.toList());


//        List<String> collect = baseSensorInfoNowPos.stream().map(t -> t.getPointMonitorLocation()).collect(Collectors.toList());
        //使用并行流
        ArrayList<PointListVO> collect = sensorMonitorNowPos.parallelStream()
                .map(t -> {
                    PointListVO pointListVO = new PointListVO();
                    pointListVO.setPointCode(t.getPointCode());
                    pointListVO.setLocation(t.getPointLocation() == null ? "" : t.getPointLocation());
                    return pointListVO;
                })
                .collect(Collectors.toCollection(ArrayList::new));

        //排序 降序
//        Collections.sort(collect, Collections.reverseOrder());
        // 使用自定义比较器按照 pointCode 进行排序
//        Collections.sort(collect, Comparator.comparing(PointListVO::getLocation, Comparator.nullsLast(Comparator.naturalOrder())));
        return collect;
    }

    /**
     * 更新关键区域测点配置信息
     *
     * @param dataConfiginfoDto
     * @return
     */
    @Override
    public Boolean upDataConfiginfo(DataConfiginfoDto dataConfiginfoDto) {
        //获取配置表唯一记录

        LambdaQueryWrapper<SensorImportanceConfigPo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //工作面名称
        lambdaQueryWrapper.eq(SensorImportanceConfigPo::getWorkName, dataConfiginfoDto.getWorkFaceName());
        //序号
        lambdaQueryWrapper.eq(SensorImportanceConfigPo::getSensorOrder, dataConfiginfoDto.getPointOrder());
        //煤矿编码
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(dataConfiginfoDto.getMineCode()), SensorImportanceConfigPo::getMineCode, dataConfiginfoDto.getMineCode());
        //查询配置表当前要更新得记录
        SensorImportanceConfigPo sensorImportanceConfigPo = sensorImportanceConfigMapper.selectOne(lambdaQueryWrapper);
        if (sensorImportanceConfigPo == null) {
            throw new HuaNengException(Constants.FAIL, "根据工作面名称和序号未查询到记录，无法做出更新操作");
        }
        //查询base基础表
        BaseSensorInfoNowPo baseSensorInfoNowPo = baseSensorInfoNowMapper.selectOne(new LambdaQueryWrapper<BaseSensorInfoNowPo>()
                //测点编码
                .eq(BaseSensorInfoNowPo::getPointCode, dataConfiginfoDto.getPointCode())
                .eq(BaseSensorInfoNowPo::getPointMonitorLocation, dataConfiginfoDto.getLocation())
                .eq(StringUtils.isNotBlank(dataConfiginfoDto.getMineCode()), BaseSensorInfoNowPo::getMineCode, dataConfiginfoDto.getMineCode()));
        if (baseSensorInfoNowPo == null) {
            throw new HuaNengException(Constants.FAIL, "查询Base表异常，暂无此测点位置记录，请选择其他location进行更新");
        }
        //测点编码
        sensorImportanceConfigPo.setPointCode(baseSensorInfoNowPo.getPointCode());
        //传感器位置信息
        sensorImportanceConfigPo.setPointMonitorLocation(baseSensorInfoNowPo.getPointMonitorLocation());
        //传感器位置别名
        sensorImportanceConfigPo.setLocationAlias(dataConfiginfoDto.getName());

        int update = sensorImportanceConfigMapper.update(sensorImportanceConfigPo, lambdaQueryWrapper);
        if (update == 1) {
            return true;
        }
        return false;
    }

    /**
     * 获取安全监控BaseSensorTable表所有信息
     *
     * @return
     */
    @Override
    public List<BaseSensorCoordDto> getBaseSensorTableAllList(String mineCode) {
        //获取所有信息  如果没有煤矿编码 默认查询所有
        LambdaQueryWrapper<BaseSensorInfoNowPo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(mineCode), BaseSensorInfoNowPo::getMineCode, mineCode);
        List<BaseSensorInfoNowPo> baseSensorInfoNowPoList = baseSensorInfoNowMapper.selectList(queryWrapper);

        //获取字典类型
        List<SysDictData> redisTypeList = RedisUtils.getCacheObject(Constants.SYS_DICT_KEY + "aqjk_sensor_type");
        //根据字典值转成map 重复的取第一个
        Map<String, SysDictData> redisTypeMap = redisTypeList.stream()
                .filter(p -> p.getDictValue() != null)
                .collect(Collectors.toMap(SysDictData::getDictValue, p -> Optional.ofNullable(p).orElse(new SysDictData()), (existing, replacement) -> replacement));
        return baseSensorInfoNowPoList.stream().map(t -> {
                    BaseSensorCoordDto baseSensorCoordDto = new BaseSensorCoordDto();
                    //传感器编码
                    baseSensorCoordDto.setPointCode(t.getPointCode());
                    //传感器名称
                    baseSensorCoordDto.setLocation(t.getPointMonitorLocation());
                    //传感器类型编码
                    baseSensorCoordDto.setSensorTypeCode(t.getSensorType());
                    //传感器类型名称
                    SysDictData sysDictData = redisTypeMap.get(t.getSensorType());
                    if (t.getSensorTypeName() != null) {
                        //优先使用基础表
                        baseSensorCoordDto.setSensorTypeName(t.getSensorTypeName() != null ? t.getSensorTypeName() : t.getSensorType());
                    } else {
                        if (sysDictData != null) {
                            baseSensorCoordDto.setSensorTypeName(sysDictData.getDictLabel() != null ? sysDictData.getDictLabel() : "");
                        } else {
                            baseSensorCoordDto.setSensorTypeName(t.getSensorTypeName() != null ? t.getSensorTypeName() : t.getSensorType());
                        }
                    }
                    //x
                    baseSensorCoordDto.setXCoordinate(t.getXCoordinate());
                    //y
                    baseSensorCoordDto.setYCoordinate(t.getYCoordinate());
                    //z
                    baseSensorCoordDto.setZCoordinate(t.getZCoordinate());
                    return baseSensorCoordDto;
                }).sorted(Comparator.comparing(BaseSensorCoordDto::getSensorTypeName))
                .collect(Collectors.toList());
    }

    @Override
    public List<OutLimitAlarmingInfoVO> alarmInfoList(String mineCode) {
        //获取字典煤矿信息
        SysOrganization sysOrganization = RedisUtils.getCacheObject(Constants.SYS_CODE_KEY + mineCode);
        if (sysOrganization == null) {
            throw new HuaNengException(Constants.FAIL, "煤矿编码出错，请检查词典" + mineCode);
        }
        //查询今日报警信息
        LambdaQueryWrapper<SensorAlarmCountStatPo> wrapper = new LambdaQueryWrapper<>();
        //煤矿编码
        wrapper.like(StringUtils.isNotBlank(mineCode), SensorAlarmCountStatPo::getMineCode, mineCode);
        //查询今天的数据
        wrapper.ge(SensorAlarmCountStatPo::getBeginTime, LocalDate.now());
        //报警类型为 超限报警
        wrapper.eq(SensorAlarmCountStatPo::getOutlierType, "001");
        wrapper.orderByDesc(SensorAlarmCountStatPo::getBeginTime);

        List<SensorAlarmCountStatPo> sensorAlarmCountStatPos = sensorAlarmCountStatMapper.selectList(wrapper);
        if (sensorAlarmCountStatPos.isEmpty()) {
            return new ArrayList<>();
        }
        List<OutLimitAlarmingInfoVO> collect = sensorAlarmCountStatPos.stream().map(t -> {
            OutLimitAlarmingInfoVO outLimitAlarmingInfoVO = new OutLimitAlarmingInfoVO();
            //煤矿编码
            outLimitAlarmingInfoVO.setMineCode(mineCode);
            //煤矿名称
            outLimitAlarmingInfoVO.setMineName(sysOrganization.getOrgName());
            //测点编码
            outLimitAlarmingInfoVO.setPointCode(t.getPointCode());
            //报警类型
            outLimitAlarmingInfoVO.setAlarmType(t.getOutlierType());
            //报警类型名称
            outLimitAlarmingInfoVO.setAlarmTypeName(t.getOutlierTypeName());
            //报警开始时间
            outLimitAlarmingInfoVO.setAlarmBeginTime(t.getBeginTime());
            //报警结束时间
            outLimitAlarmingInfoVO.setAlarmEndTime(t.getEndTime());
            //报警最大值
            outLimitAlarmingInfoVO.setAlarmMaxValue(t.getMaxValue());
            //传感器位置
            outLimitAlarmingInfoVO.setPointLocation(t.getPointLocation());
            //报警时长
            outLimitAlarmingInfoVO.setAlarmDuration(getDuration(t.getBeginTime(), t.getEndTime()));
            //报警原因
            outLimitAlarmingInfoVO.setAlarmCause(t.getAbnormalCause());
            //处理措施
            outLimitAlarmingInfoVO.setMeasure(t.getMeasure());
            //处置状态   判断措施是否有值
            outLimitAlarmingInfoVO.setStatus(StringUtils.isNotBlank(t.getMeasure()) ? "完成" : "未完成");
            //备注
            outLimitAlarmingInfoVO.setRemark("");
            return outLimitAlarmingInfoVO;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public GasAnalysisVo getCurrentGasTrend() {
        GasAnalysisVo result = new GasAnalysisVo();
        List<ChartAnaliseVo> chartData = new ArrayList<>();
        String endTime = DateUtils.getTime();
        String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, DateUtils.getNowDate())+ " 00:00:00";
        List<String> xData = OweDateUtils.getXData(startTime, endTime, "minutes");
        String sql = "SELECT \n" +
                "    time_bucket('1 minute', hs.data_time) AS dataTime,\n" +
                "\t\tbs.point_monitor_location pointName,\n" +
                "    max(hs.point_value) AS pointValue         \n" +
                "FROM\n" +
                "\tdwd_aqjk_now_base_sensorinfo bs\n" +
                "\tLEFT JOIN dwd_aqjk_his_sensormonitor hs on bs.point_code=hs.point_code\n" +
                "\tWHERE bs.sensor_type='0001' and hs.data_time>='%s' AND hs.data_time<='%s'\n" +
                "GROUP BY \n" +
                "    dataTime,bs.point_monitor_location";
        sql = String.format(sql, startTime, endTime);
        List<Map<String, Object>> maps = monitorJdbcTemplate.queryForList(sql);
        xData.remove(xData.size() - 1);
        xData.forEach(x -> {
            ChartAnaliseVo chartAnaliseVo = new ChartAnaliseVo();
            List<Map<String, Object>> datas = maps.stream().filter(t -> x.equals(t.get("dataTime"))).collect(Collectors.toList());
            if (!datas.isEmpty()) {
                double sum = datas.stream().mapToDouble(u -> Double.parseDouble(u.get("pointValue").toString())).sum();
                chartAnaliseVo.setY(sum + "");
            } else {
                chartAnaliseVo.setY("0.0");
            }
            chartAnaliseVo.setX(x);
            chartData.add(chartAnaliseVo);
        });
        result.setChartData(chartData);
        result.setCoalFaceName("工作面");
        result.setGasValue("0.0");
        if (!maps.isEmpty()) {
            List<Map<String, Object>> collect = maps.stream().filter(u -> StringUtils.equals("工作面", u.get("pointName").toString())).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                List<Map<String, Object>> dataTime = collect.stream().sorted(Comparator.comparing(t -> t.get("dataTime").toString())).collect(Collectors.toList());
                Map<String, Object> stringObjectMap = dataTime.get(dataTime.size() - 1);
                result.setGasValue(stringObjectMap.get("pointValue").toString());
                result.setCoalFaceName(stringObjectMap.get("pointName").toString());
            }
        }
        return result;
    }

    /**
     * 获取间隔 时 分 秒
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return
     */
    private String getDuration(Date startTime, Date endTime) {
        LocalDateTime startDateTime = LocalDateTime.ofInstant(startTime.toInstant(), java.time.ZoneId.systemDefault());
        LocalDateTime endDateTime = LocalDateTime.ofInstant(endTime.toInstant(), java.time.ZoneId.systemDefault());
        Duration duration = Duration.between(startDateTime, endDateTime);
        long minutes = duration.toMinutes(); // 获取分钟数
        long seconds = duration.minusMinutes(minutes).getSeconds(); // 获取剩余的秒数
        String timeString = "";
        if (duration.toHours() < 1) {
            timeString = minutes + "分钟" + seconds + "秒";
        } else {
            timeString = duration.toHours() + "小时" + minutes + "分钟" + seconds + "秒";
        }
        return timeString;
    }

    public String getKeyAreasType(String type) {
        if ("温度".equals(type)) {
            return "环境温度";
        } else if ("一氧化碳".equals(type)) {
            return "一氧化碳";
        } else if ("甲烷".equals(type)) {
            return "环境瓦斯";
        } else if ("风速".equals(type)) {
            return "风速";
        } else {
            return "未知类型";
        }


    }


}
